#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace Xfinity.Rendering
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class LensFlare : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private ContentManager content;
        private Texture2D lensFlare, lens1, lens2, lens3;
        private ICamera camera;
        private SpriteBatch batch;
        public LensFlare(Vector3 direction, Game game)
            : base(game)
        {
            SunDirection = direction;
            content = new ContentManager(game.Services);

        }
        #region SunDirection
        private Vector3 sunDir;

        /// <summary>
        /// SunDirection.
        /// </summary>
        public Vector3 SunDirection
        {
            [System.Diagnostics.DebuggerStepThroughAttribute]
            get { return sunDir; }
            [System.Diagnostics.DebuggerStepThroughAttribute]
            set
            {
                sunDir = value;
                sunDir.X = -sunDir.X;
            }
        }
        #endregion

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here
            //sunDir = Vector3.One;
            sunDir.Normalize();
            base.Initialize();
        }

        protected override void LoadGraphicsContent(bool loadAllContent)
        {
            if (loadAllContent)
            {
                camera = ((ICameraHolder)Game.Services.GetService(typeof(ICameraHolder))).ActiveCamera;
                lensFlare = content.Load<Texture2D>(@"Content\Textures\lensFlare");
                lens1 = content.Load<Texture2D>(@"Content\Textures\lens1");
                lens2 = content.Load<Texture2D>(@"Content\Textures\lens2");
                lens3 = content.Load<Texture2D>(@"Content\Textures\lens3");
                batch = new SpriteBatch(GraphicsDevice);
            }
            base.LoadGraphicsContent(loadAllContent);
        }
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here

            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            Vector3 projected3d = Vector3.TransformNormal(sunDir, camera.World * camera.View * camera.Projection);
            if (projected3d.X > 1 || projected3d.X < -1 || projected3d.Y > 1 || projected3d.Y < -1 || projected3d.Z < 0)
            {
                return;
            }

            Vector2 screenSunPos = new Vector2(projected3d.X / projected3d.Z, -projected3d.Y / projected3d.Z);

            Vector2 absoluteSunPos = GetAbsolutePosition(screenSunPos);

            Vector2 firstFlarePos = absoluteSunPos;
            Vector2 firstHaloPos = GetAbsolutePosition((screenSunPos * (1 / 2f)));
            Vector2 firstBurstPos = GetAbsolutePosition((screenSunPos * (1 / 3f)));

            Vector2 secondHalo = GetAbsolutePosition((screenSunPos * (1 / 8f)));
            Vector2 secondBurst = GetAbsolutePosition((screenSunPos * (-1 / 2f)));

            Vector2 thirdHalo = GetAbsolutePosition((screenSunPos * (-1 / 4f)));
            Vector2 thirdBurst = GetAbsolutePosition((screenSunPos * (-1 / 5.5f)));

            batch.Begin(SpriteBlendMode.Additive, SpriteSortMode.BackToFront, SaveStateMode.None);

            Rectangle rect = new Rectangle((int)absoluteSunPos.X - 128, (int)absoluteSunPos.Y - 128, 256, 256);
            batch.Draw(lensFlare, rect, Color.White);
            batch.Draw(lens1, firstHaloPos - new Vector2(32), null, Color.White, 0, Vector2.Zero, .5f, SpriteEffects.None, 0);
            batch.Draw(lens2, firstBurstPos - vector264, Color.White);
            batch.Draw(lens3, secondHalo - vector264, Color.White);
            batch.Draw(lens1, secondBurst - vector264, Color.White);
            batch.Draw(lens2, thirdHalo - vector264, Color.White);
            batch.Draw(lens3, thirdBurst - vector264, Color.White);
            batch.End();
            //GraphicsDevice.RenderState.DepthBufferEnable = true;
            //GraphicsDevice.RenderState.AlphaBlendEnable = false;

            base.Draw(gameTime);
        }
        private Vector2 vector264 = new Vector2(64);
        private Vector2 GetAbsolutePosition(Vector2 screenPosition)
        {
            Vector2 absoluteSunPos;
            absoluteSunPos.X = ((screenPosition.X + 1) * .5f) * GraphicsDevice.Viewport.Width;
            absoluteSunPos.Y = ((screenPosition.Y + 1) * .5f) * GraphicsDevice.Viewport.Height;
            return absoluteSunPos;
        }
    }
}


